﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Transactions;

namespace zijian666.Data
{
    /// <summary>
    /// 扩展方法
    /// </summary>
    public static class DbConnectionExtensions
    {
        /// <summary>
        /// 查询列表时的默认的最大返回行数
        /// </summary>
        public const int DEFAULT_LIMIT = 100000;

        /// <summary>
        /// 如果数据库连接当前为关闭状态, 则打开返回 <code>true</code>, 否则返回 <code>false</code>
        /// <para> 如果 <paramref name="conn"/> 为null, 也返回 <code>false</code> </para>
        /// </summary>
        /// <param name="conn"></param>
        public static bool OpenIfClosed(this IDbConnection conn)
        {
            if (conn == null)
            {
                return false;
            }
            if (conn.State != ConnectionState.Open)
            {
                conn.Open();
                Diagnostic.Wirte("Connect", "Open");
                return true;
            }
            return false;
        }

        /// <summary>
        /// 关闭数据库连接, 不返回任何错误
        /// </summary>
        /// <param name="conn"></param>
        public static void SafeClose(this IDbConnection conn)
        {
            try
            {
                if (conn?.State == ConnectionState.Open)
                {
                    conn.Close();
                    Diagnostic.Wirte("Connect", "Close");
                }
            }
            catch (Exception ex)
            {
                Diagnostic.Error(ex);
            }
        }

        /// <summary>
        /// 保持数据库连接打开状态, 并返回一个 <see cref="IDisposable"/> 对象, 在 <see cref="IDisposable.Dispose"/> 时关闭数据库连接
        /// </summary>
        /// <param name="conn"></param>
        /// <returns></returns>
        public static IDisposable OpenScope(this IDbConnection conn) => new OpenScope(conn);

        /// <summary>
        /// 使用 sql语句(<paramref name="fsql"/>) 创建数据库执行命令(<see cref="IDbCommand"/>)
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="fsql"></param>
        /// <returns></returns>
        public static IDbCommand CreateCommand(this IDbConnection conn, FormattableString fsql) => CreateCommand(conn, fsql, (FormattableString[])null);


        /// <summary>
        /// 使用 sql语句(<paramref name="fsql"/>) 创建数据库执行命令(<see cref="IDbCommand"/>)
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="fsqls"></param>
        /// <returns></returns>
        public static IDbCommand CreateCommand(this IDbConnection conn, FormattableString fsql, params FormattableString[] fsqls)
        {
            if (conn is null)
            {
                throw new ArgumentNullException(nameof(conn));
            }
            if ((fsql is null || string.IsNullOrWhiteSpace(fsql.Format)) && (fsqls is null || fsqls.Length == 0))
            {
                throw new ArgumentNullException(nameof(fsql));
            }

            var cmd = conn.CreateCommand();
            cmd.CommandType = CommandType.Text;

            using (ObjectPoolHelper.GetDbParameterFormatProvider(out var provider))
            {
                provider.SetCommand(cmd);
                if (!(fsql is null))
                {
                    cmd.CommandText = fsql.ToString(provider);
                }
                if (!(fsqls is null) && fsqls.Length > 0)
                {
                    if (cmd.CommandText?.Length > 0 && !cmd.CommandText.EndsWith(';'))
                    {
                        cmd.CommandText += ";\n";
                    }
                    cmd.CommandText += string.Join(";\n", fsqls.Select(x => x.ToString(provider).Trim(';'))) + ";";
                }
            }
            if (Diagnostic.IsEnabled)
            {
                Diagnostic.Wirte("SQL", cmd.CommandText);
                Diagnostic.Wirte("SQLParams", string.Join("; ", cmd.Parameters.Cast<IDataParameter>().Select(x => $"{x.ParameterName}: {x.Value}({x.DbType})")));
            }
            return cmd;
        }

        /// <summary>
        /// 将 <paramref name="value"/> 添加到 <paramref name="command"/>
        /// </summary>
        public static IDbDataParameter AddParameter(this IDbCommand command, object value)
        {
            if (command is null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            var p = command.CreateParameter();
            p.Value = value.GetDbObject();
            command.Parameters.Add(p);
            return p;
        }

        /// <summary>
        /// 执行委托 <paramref name="func"/>
        /// <para> 如果数据库连接未打开, 则打开, 执行完毕后关闭连接 </para>
        /// <para> 如果数据库连接已打开则直接执行委托, 执行完毕后也不关闭连接 </para>
        /// </summary>
        public static T Execute<T>(this IDbConnection conn, Func<T> func)
        {
            if (conn is null || func is null)
            {
                throw new ArgumentNullException(func is null ? nameof(func) : nameof(conn));
            }

            using (new SelfClosingDbCommand(conn))
            {
                return func();
            }
        }

        /// <summary>
        /// 执行委托 <paramref name="action"/>
        /// <para> 如果数据库连接未打开, 则打开, 执行完毕后关闭连接 </para>
        /// <para> 如果数据库连接已打开则直接执行委托, 执行完毕后也不关闭连接 </para>
        /// </summary>
        public static void Execute(this IDbConnection conn, Action action)
        {
            if (conn is null)
            {
                throw new ArgumentNullException(nameof(conn));
            }

            if (action is null)
            {
                return;
            }

            using (new SelfClosingDbCommand(conn))
            {
                action();
            }
        }

        /// <summary>
        /// 执行事务, 除非 <paramref name="action"/> 抛出异常, 否则直接提交
        /// <para> 如果数据库连接未打开, 则打开, 执行完毕后关闭连接 </para>
        /// <para> 如果数据库连接已打开则直接执行委托, 执行完毕后也不关闭连接 </para>
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="action"></param>
        public static void Transaction(this IDbConnection conn, Action action)
        {
            using (new SelfClosingDbCommand(conn))
            using (var tran = new TransactionScope())
            {
                Diagnostic.Wirte("Transaction", "Begin");
                action();
                tran.Complete();
                Diagnostic.Wirte("Transaction", "Commit");
            }
        }

        /// <summary>
        /// 执行事务, 除非 <paramref name="func"/> 抛出异常, 否则直接提交
        /// <para> 如果数据库连接未打开, 则打开, 执行完毕后关闭连接 </para>
        /// <para> 如果数据库连接已打开则直接执行委托, 执行完毕后也不关闭连接 </para>
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="func"></param>
        public static T Transaction<T>(this IDbConnection conn, Func<T> func)
        {
            using (new SelfClosingDbCommand(conn))
            using (var tran = new TransactionScope())
            {
                Diagnostic.Wirte("Transaction", "Begin");
                var result = func();
                tran.Complete();
                Diagnostic.Wirte("Transaction", "Commit");
                return result;
            }
        }

        /// <summary>
        /// 执行sql, 处理 <see cref="IDataReader"/>
        /// </summary>
        public static void ExecuteReader(this IDbConnection conn, FormattableString sql, Action<IDataReader> action)
        {
            if (conn is null)
            {
                throw new ArgumentNullException(nameof(conn));
            }

            if (sql is null)
            {
                throw new ArgumentNullException(nameof(sql));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var command = conn.CreateCommand(sql);
            using (new SelfClosingDbCommand(command))
            {
                ExecuteReader(command, action);
            }
        }

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 处理 <see cref="IDataReader"/>
        /// </summary>
        public static void ExecuteReader(this IDbCommand command, Action<IDataReader> action)
        {
            if (command is null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            if (action is null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            using (ObjectPoolHelper.GetStopwatch(out var sw))
            {
                sw.Start();
                var reader = command.ExecuteReader();
                Diagnostic.Wirte("Executing", sw.ElapsedMilliseconds + " ms");
                using (new SelfClosingDataReader(reader, command))
                {
                    action(reader);
                }
                Diagnostic.Wirte("Executed", sw.ElapsedMilliseconds + " ms");
            }
        }

        /// <summary>
        /// 执行sql, 处理 <see cref="IDataReader"/>, 并返回数据
        /// </summary>
        public static T ExecuteReader<T>(this IDbConnection conn, FormattableString sql, Func<IDataReader, T> func)
        {
            if (conn is null)
            {
                throw new ArgumentNullException(nameof(conn));
            }

            if (sql is null)
            {
                throw new ArgumentNullException(nameof(sql));
            }

            if (func is null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            var command = conn.CreateCommand(sql);
            using (new SelfClosingDbCommand(command))
            {
                return ExecuteReader(command, func);
            }
        }

        /// <summary>
        /// 执行<see cref="IDbCommand"/>, 处理 <see cref="IDataReader"/>, 并返回数据
        /// </summary>
        public static T ExecuteReader<T>(this IDbCommand command, Func<IDataReader, T> func)
        {
            if (command is null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            if (func is null)
            {
                throw new ArgumentNullException(nameof(func));
            }

            using (ObjectPoolHelper.GetStopwatch(out var sw))
            {
                sw.Start();
                var reader = command.ExecuteReader();
                Diagnostic.Wirte("Executing", sw.ElapsedMilliseconds + " ms");
                using (new SelfClosingDataReader(reader, command))
                {
                    var result = func(reader);
                    Diagnostic.Wirte("Executed", sw.ElapsedMilliseconds + " ms");
                    return result;
                }
            }
        }

        /// <summary>
        /// 执行查询命令返回受影响行数
        /// </summary>
        /// <returns></returns>
        public static int ExecuteNonQuery(this IDbConnection conn, FormattableString sql) => ExecuteNonQuery(conn, sql, (FormattableString[])null);


        /// <summary>
        /// 执行查询命令返回受影响行数
        /// </summary>
        /// <returns></returns>
        public static int ExecuteNonQuery(this IDbConnection conn, FormattableString sql, params FormattableString[] sqls)
        {
            var command = conn.CreateCommand(sql, sqls);
            using (new SelfClosingDbCommand(command))
            using (ObjectPoolHelper.GetStopwatch(out var sw))
            {
                sw.Start();
                var result = command.ExecuteNonQuery();
                Diagnostic.Wirte("Executed", sw.ElapsedMilliseconds + " ms");
                return result;
            }
        }

        /// <summary>
        /// 执行查询命令返回受影响行数
        /// </summary>
        /// <returns></returns>
        public static int ExecuteNonQuery(this IDbConnection conn, FormattableString[] sqls) => ExecuteNonQuery(conn, null, sqls);


        /// <summary>
        /// 执行sql, 返回实体类集合
        /// </summary>
        public static List<T> ExecuteList<T>(this IDbConnection conn, FormattableString sql, int limit = DEFAULT_LIMIT)
            => conn.ExecuteReader(sql, reader => reader.ReadList<T>(limit));

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回实体类集合
        /// </summary>
        public static List<T> ExecuteList<T>(this IDbCommand command, int limit = DEFAULT_LIMIT)
            => ExecuteReader(command, reader => reader.ReadList<T>(limit));

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中的数据，并返回动态集合 <see cref="List{dynamic}"/>
        /// </summary>
        public static List<T> ReadList<T>(this IDataReader reader, int limit = DEFAULT_LIMIT)
        {
            if (typeof(object) == typeof(T))
            {
                return (List<T>)(object)reader.ReadList(limit);
            }

            return EntityBuilder.GetBuilder<T>().ToMultiple(reader).Take(limit).ToList();
        }

        /// <summary>
        /// 执行sql, 返回动态对象集合
        /// </summary>
        public static List<dynamic> ExecuteList(this IDbConnection conn, FormattableString sql, int limit = DEFAULT_LIMIT)
            => conn.ExecuteReader(sql, reader => reader.ReadList(limit));

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回动态对象集合
        /// </summary>
        public static List<dynamic> ExecuteList(this IDbCommand command, int limit = DEFAULT_LIMIT)
            => ExecuteReader(command, reader => reader.ReadList(limit));

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中的数据，并返回动态集合 <see cref="List{dynamic}"/>
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static List<dynamic> ReadList(this IDataReader reader, int limit = DEFAULT_LIMIT)
        {
            var mapping = reader.GetFieldMapping();
            var list = new List<dynamic>();
            for (var i = 0; i < limit && reader.Read(); i++)
            {
                var values = new object[reader.FieldCount];
                reader.GetValues(values);
                list.Add(new DynamicRecord(mapping, values));
            }
            return list;
        }

        /// <summary>
        /// 获取 <see cref="IDataReader"/> 中字段
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, int> GetFieldMapping(this IDataReader reader)
        {
            var fieldCount = reader.FieldCount;
            var mapping = new Dictionary<string, int>(fieldCount, StringComparer.OrdinalIgnoreCase);
            for (var i = 0; i < fieldCount; i++)
            {
                mapping.Add(reader.GetName(i), i);
            }
            return mapping;
        }

        /// <summary>
        /// 执行sql, 返回第一行数据的实体类型对象
        /// </summary>
        public static T ExecuteFirst<T>(this IDbConnection conn, FormattableString sql)
            => conn.ExecuteReader(sql, reader => reader.Read() ? EntityBuilder.GetBuilder<T>().ToSingle(reader) : default);

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回第一行数据的实体类型对象
        /// </summary>
        public static T ExecuteFirst<T>(this IDbCommand command)
            => ExecuteReader(command, reader => reader.Read() ? EntityBuilder.GetBuilder<T>().ToSingle(reader) : default);

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中下一行的数据，并返回实体类型对象
        /// </summary>]
        /// <returns></returns>
        public static T ReadSingle<T>(this IDataReader reader)
            => reader.Read() ? ToSingle<T>(reader) : default;

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中当前行的数据，并返回实体类型对象
        /// </summary>]
        /// <returns></returns>
        public static T ToSingle<T>(this IDataReader reader)
            => EntityBuilder.GetBuilder<T>().ToSingle(reader);

        /// <summary>
        /// 执行sql, 返回第一行数据的动态对象
        /// </summary>
        /// <returns></returns>
        public static dynamic ExecuteFirst(this IDbConnection conn, FormattableString sql)
            => conn.ExecuteReader(sql, reader => reader.ReadSingle());

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回第一行数据的动态对象
        /// </summary>
        public static dynamic ExecuteFirst(this IDbCommand command, FormattableString sql)
            => ExecuteReader(command, reader => reader.ReadSingle());


        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中下一行的数据，并返回动态类型对象
        /// </summary>]
        /// <returns></returns>
        public static dynamic ReadSingle(this IDataReader reader)
            => reader.Read() ? ToSingle(reader) : null;

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中当前行的数据，并返回动态类型对象
        /// </summary>]
        /// <returns></returns>
        public static dynamic ToSingle(this IDataReader reader)
        {
            var mapping = reader.GetFieldMapping();
            var values = new object[reader.FieldCount];
            reader.GetValues(values);
            return new DynamicRecord(mapping, values);
        }


        /// <summary>
        /// 执行sql, 返回第一行第一列的数据
        /// </summary>
        public static T ExecuteScalar<T>(this IDbConnection conn, FormattableString sql, T defaultValue = default)
            => conn.ExecuteReader(sql, reader => reader.ReadScalar(defaultValue));

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回第一行第一列的数据
        /// </summary>
        public static T ExecuteScalar<T>(this IDbCommand command, T defaultValue = default)
            => ExecuteReader(command, reader => reader.ReadScalar(defaultValue));

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中下一行第一列的数据
        /// </summary>
        public static T ReadScalar<T>(this IDataReader reader, T defaultValue = default)
            => reader.Read() ? ToScalar<T>(reader) : defaultValue;

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中当前行第一列的数据
        /// </summary>
        public static T ToScalar<T>(this IDataReader reader)
            => EntityBuilder.Read<T>(reader, 0);


        /// <summary>
        /// 执行sql, 返回第一行第一列的动态对象
        /// </summary>
        public static dynamic ExecuteScalar(this IDbConnection conn, FormattableString sql, object defaultValue = null)
            => conn.ExecuteReader(sql, reader => reader.ReadScalar(defaultValue));

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回第一行第一列的动态对象
        /// </summary>
        public static dynamic ExecuteScalar(this IDbCommand command, FormattableString sql, object defaultValue = null)
            => ExecuteReader(command, reader => reader.ReadScalar(defaultValue));

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中下一行第一列的动态对象
        /// </summary>
        public static dynamic ReadScalar(this IDataReader reader, object defaultValue = null)
            => reader.Read() ? ToScalar(reader) : (dynamic)new DynamicAtom(defaultValue);

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中当前行第一列的动态对象
        /// </summary>
        public static dynamic ToScalar(this IDataReader reader)
            => new DynamicAtom(reader.GetValue(0));

        /// <summary>
        /// 执行sql, 返回 <see cref="DataTable"/>
        /// </summary>
        public static DataTable ExecuteDataTable(this IDbConnection conn, FormattableString sql, int limit = DEFAULT_LIMIT)
            => conn.ExecuteReader(sql, reader => reader.ReadDataTable(limit));

        /// <summary>
        /// 执行 <see cref="IDbCommand"/>, 返回 <see cref="DataTable"/>
        /// </summary>
        public static DataTable ExecuteDataTable(this IDbCommand command, int limit = DEFAULT_LIMIT)
            => ExecuteReader(command, reader => reader.ReadDataTable(limit));

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中的数据，并返回 <see cref="DataTable"/>
        /// </summary>
        public static DataTable ReadDataTable(this IDataReader reader, int limit = DEFAULT_LIMIT)
        {
            var table = reader.ToDataTable();
            var values = new object[reader.FieldCount];
            for (var i = 0; i < limit && reader.Read(); i++)
            {
                reader.GetValues(values);
                table.LoadDataRow(values, LoadOption.OverwriteChanges); // TODO: 我想知道1和3的区别
            }
            return table;
        }
        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中的字段和类型，并返回没有数据的 <see cref="DataTable"/>
        /// </summary>
        public static DataTable ToDataTable(this IDataReader reader)
        {
            var table = new DataTable();
            var fieldCount = reader.FieldCount;
            for (var i = 0; i < fieldCount; i++)
            {
                table.Columns.Add(reader.GetName(i), reader.GetFieldType(i));
            }
            return table;
        }

        /// <summary>
        /// 执行sql, 返回 <see cref="DataRow"/>
        /// </summary>
        public static DataRow ExecuteDataRow(this IDbConnection conn, FormattableString sql)
            => conn.ExecuteReader(sql, reader => reader.ReadDataRow());

        /// <summary>
        /// 执行sql, 返回 <see cref="DataRow"/>
        /// </summary>
        public static DataRow ExecuteDataRow(this IDbCommand command, FormattableString sql)
            => ExecuteReader(command, reader => reader.ReadDataRow());

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中下一行
        /// </summary>
        public static DataRow ReadDataRow(this IDataReader reader)
            => reader.Read() ? ToDataRow(reader) : null;

        /// <summary>
        /// 读取 <see cref="IDataReader"/> 中当前行
        /// </summary>
        public static DataRow ToDataRow(this IDataReader reader)
        {
            var values = new object[reader.FieldCount];
            var table = reader.ToDataTable();
            reader.GetValues(values);
            return table.LoadDataRow(values, LoadOption.OverwriteChanges);
        }


        /// <summary>
        /// 返回执行表名的表结构
        /// </summary>
        public static DataTable GetSchemaTable(this Type type)
        {
            var tableName = type.GetCustomAttribute<TableAttribute>()?.Name ?? type.Name;

            var schemaTable = new DataTable(tableName);

            var properties = type.GetProperties();

            foreach (var property in properties)
            {
                if (property.IsDefined(typeof(NotMappedAttribute), true))
                {
                    continue;
                }
                var columnName = property.GetCustomAttribute<ColumnAttribute>()?.Name ?? property.Name;
                var columnType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;

                var column = new DataColumn(columnName, columnType)
                {
                    AllowDBNull = !property.IsDefined(typeof(RequiredAttribute)),
                    MaxLength = property.GetCustomAttribute<StringLengthAttribute>()?.MaximumLength ?? -1,
                    DefaultValue = property.GetCustomAttribute<DefaultValueAttribute>()?.Value,
                    ReadOnly = property.GetCustomAttribute<ReadOnlyAttribute>()?.IsReadOnly ?? false,
                    Unique = property.IsDefined(typeof(KeyAttribute)),
                    AutoIncrement = property.GetCustomAttribute<DatabaseGeneratedAttribute>()?.DatabaseGeneratedOption == DatabaseGeneratedOption.Identity,
                    Caption = property.GetCustomAttribute<DisplayAttribute>()?.Name
                            ?? property.GetCustomAttribute<DescriptionAttribute>()?.Description
                            ?? property.Name
                };
                schemaTable.Columns.Add(column);
            }

            return schemaTable;
        }

        /// <summary>
        /// 返回执行表名的表结构
        /// </summary>
        public static DataTable GetSchemaTable(this IDbConnection connection, string tableName)
        {
            using var command = connection.CreateCommand();
            using (new SelfClosingDbCommand(command))
            {
                command.CommandText = $"SELECT * FROM {tableName} WHERE 1 = 2";
                command.CommandType = CommandType.Text;
                using var reader = command.ExecuteReader(CommandBehavior.SchemaOnly);
                var schemaTable = reader.GetSchemaTable();
                schemaTable.TableName = tableName;
                return schemaTable;
            }
        }

        /// <summary>
        /// 将实体类集合<paramref name="data"/>填充到 <see cref="DataTable"/> <paramref name="table"/> 中
        /// </summary>
        public static DataTable FillData<T>(this DataTable table, IEnumerable<T> data)
        {
            var properties = typeof(T).GetProperties().Where(x => table.Columns.Contains(x.Name)).ToArray();
            foreach (var item in data.Where(x => x != null))
            {
                var row = table.NewRow();

                foreach (var property in properties)
                {
                    var value = property.GetValue(item);
                    row[property.Name] = value ?? DBNull.Value;
                }

                table.Rows.Add(row);
            }
            return table;
        }

        /// <summary>
        /// 按 <paramref name="schemaTable"/> 数据表结构创建空白表 <seealso cref="DataTable"/>
        /// </summary>
        public static DataTable BuildDataTable(this DataTable schemaTable)
        {
            var table = new DataTable(schemaTable.TableName);
            foreach (DataRow row in schemaTable.Rows)
            {
                var columnName = row.Field<string>("ColumnName");
                var columnType = row.Field<Type>("DataType");
                var column = new DataColumn(columnName, columnType)
                {
                    AllowDBNull = row.Field<bool?>("AllowDBNull") ?? true,
                    Unique = row.Field<bool?>("IsUnique") ?? false,
                };

                if (columnType == typeof(string))
                {
                    column.MaxLength = row.Field<int?>("ColumnSize") ?? -1;
                }
                table.Columns.Add(column);
            }
            return table;
        }

    }
}
